package com.hefan.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cat.common.constant.RedisKeyConstant;
import com.cat.common.entity.Page;
import com.cat.common.meta.UserTypeEnum;
import com.cat.common.meta.WebUserCachTypeEnum;
import com.cat.tiger.service.JedisService;
import com.hefan.user.bean.WebUser;
import com.hefan.user.bean.WebUserIdentity;
import com.hefan.user.config.UserConfigCenter;
import com.hefan.user.dao.WebUserDao;
import com.hefan.user.itf.UserCacheService;
import com.hefan.user.itf.WebUserService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

/**
 * 用户信息缓存处理
 * Created by lxw on 2016/10/24.
 */
@Component("userCacheService")
public class UserCacheServiceImpl implements UserCacheService {
  private Logger logger = LoggerFactory.getLogger(UserCacheServiceImpl.class);

  @Resource
  private WebUserDao webUserDao;
  @Resource
  private JedisService jedisService;
  @Resource
  private UserConfigCenter userConfigCenter;
  @Resource
  private WebUserService webUserService;

  @Override
  public WebUser findUserInfoFromRedis(String userId) {
    WebUser webUser = null;
    try {
      String userInfoKey = String.format(RedisKeyConstant.WEB_USER_INFO_KEY, userId);
      String resStr = jedisService.getStr(userInfoKey);
      if (StringUtils.isNotBlank(resStr)) {
        webUser = JSON.parseObject(resStr, WebUser.class);
        this.getAllUserCach(webUser);
      }
    } catch (Exception e) {
      logger.error(e.getMessage());
    }
    return webUser;
  }

  @Override
  public void setUserInfoToRedis(WebUser webUser) {
    try {
      if (webUser != null) {
        String userInfoKey = String.format(RedisKeyConstant.WEB_USER_INFO_KEY, webUser.getUserId());
        jedisService.setexStr(userInfoKey, JSON.toJSONString(webUser), RedisKeyConstant.WEB_USER_INFO_SECONDS);
      }
    } catch (Exception e) {
      logger.error(e.getMessage());
    }
  }

  @Override
  public long delUserBaseInfoCach(String userId) {
    long res = 0;
    try {
      String userInfoKey = String.format(RedisKeyConstant.WEB_USER_INFO_KEY, userId);
      Long resRow = jedisService.del(userInfoKey);
      if(resRow != null) {
        res = resRow.longValue();
      }
    }catch (Exception e) {
      logger.error(e.getMessage());
    }
    return res;
  }

  @Override
  public WebUserIdentity findUserIdentityFromRedis(String userId) {
    WebUserIdentity webUserIdentity = null;
    try {
      String userInfoKey = String.format(RedisKeyConstant.WEB_USER_IDENTITY_KEY, userId);
      String resStr = jedisService.getStr(userInfoKey);
      if (StringUtils.isNotBlank(resStr)) {
        webUserIdentity = JSON.parseObject(resStr, WebUserIdentity.class);
      }
    } catch (Exception e) {
      logger.error(e.getMessage());
    }
    return webUserIdentity;
  }

  @Override
  public void setUserIdentityToRedis(WebUserIdentity webUserIdentity) {
    try {
      if (webUserIdentity != null) {
        String userInfoKey = String.format(RedisKeyConstant.WEB_USER_IDENTITY_KEY, webUserIdentity.getUserId());
        jedisService.setexStr(userInfoKey, JSON.toJSONString(webUserIdentity), RedisKeyConstant.WEB_USER_IDENTITY_SECONDS);
      }
    } catch (Exception e) {
      logger.error(e.getMessage());
    }
  }

  @Override
  public Long incrUserCach(String userId, WebUserCachTypeEnum webUserCachTypeEnum, long incrVal) {
    String key = WebUserCachTypeEnum.getCachKey(webUserCachTypeEnum, userId);
    try {
      if (jedisService.isExist(key)) {
        return jedisService.incrBy2(key, incrVal);
      } else {
        Long currentVal = initUserCachFromDb(userId, webUserCachTypeEnum);
        if (currentVal != null) {
          return jedisService.incrBy2(key, incrVal);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public Long getIncrUserCach(String userId, WebUserCachTypeEnum webUserCachTypeEnum) {
    String key = WebUserCachTypeEnum.getCachKey(webUserCachTypeEnum, userId);
    try {
      if (jedisService.isExist(key)) {
        return jedisService.incrBy2(key, 0);
      } else {
       return null;
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public Long getUserCach(String userId, WebUserCachTypeEnum webUserCachTypeEnum) {
    String key = WebUserCachTypeEnum.getCachKey(webUserCachTypeEnum, userId);
    try {
      if (jedisService.isExist(key)) {
        return jedisService.incrBy2(key, 0L);
      } else {
        return initUserCachFromDb(userId, webUserCachTypeEnum);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  @Override
  public void getAllUserCach(WebUser webUser) {
    if (webUser != null) {
      if (!UserTypeEnum.isAnchor(webUser.getUserType())) { //非主播用户
        //获取总经验
        Long expVal = getUserCach(webUser.getUserId(), WebUserCachTypeEnum.Exp_type);
        if (expVal != null) {
          webUser.setExp(expVal);
        }
      }
      //获取盒饭累计数
      Long hefanTotalVal = getUserCach(webUser.getUserId(), WebUserCachTypeEnum.HefanTotal_type);
      if (hefanTotalVal != null) {
        webUser.setHefanTotal(hefanTotalVal);
      }
    }
  }

  @Override
  public void initAllUserCach(WebUser webUser) {
    try {
      if (!UserTypeEnum.isAnchor(webUser.getUserType())) { //非主播用户
        //经验
        this.initUserCachSing(webUser.getUserId(), WebUserCachTypeEnum.Exp_type, webUser.getExp() == null ? 0L : webUser.getExp());
     /* } else {*/
        //累计盒饭
        //this.initUserCachSing(webUser.getUserId(), WebUserCachTypeEnum.HefanTotal_type, webUser.getHefanTotal() == null ? 0L : webUser.getHefanTotal());
      }
      //累计盒饭
      this.initUserCachSing(webUser.getUserId(), WebUserCachTypeEnum.HefanTotal_type, webUser.getHefanTotal() == null ? 0L : webUser.getHefanTotal());

      //饭票
            /*this.initUserCachSing(webUser.getUserId(),WebUserCachTypeEnum.Balance_type,webUser.getBalance() == null ?0L:webUser.getBalance());
            //累计贡献值
            this.initUserCachSing(webUser.getUserId(),WebUserCachTypeEnum.PayCount_type, webUser.getPayCount() == null ?0L:webUser.getPayCount());*/
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 初始化缓存信息
   *
   * @param userId
   * @param webUserCachTypeEnum
   * @param value
   * @throws Exception
   */
  private Long initUserCachSing(String userId, WebUserCachTypeEnum webUserCachTypeEnum, long value) throws Exception {
    String key = WebUserCachTypeEnum.getCachKey(webUserCachTypeEnum, userId);
    return jedisService.incrBy2(key, value);
  }

  /**
   * 由DB的数据进行数据初始化
   */
  private Long initUserCachFromDb(String userId, WebUserCachTypeEnum webUserCachTypeEnum) throws Exception {
    WebUser webUser = webUserDao.getWebUserBaseInfo(userId);
    if (webUser != null) {
      if (webUserCachTypeEnum.getType() == WebUserCachTypeEnum.Exp_type.getType()) { //经验
        return initUserCachSing(userId, webUserCachTypeEnum, webUser.getExp() == null ? 0L : webUser.getExp());
      } /*else  if(webUserCachTypeEnum.getType() == WebUserCachTypeEnum.Balance_type.getType()) { //饭票
                return initUserCachSing(userId,webUserCachTypeEnum, webUser.getBalance() == null ?0L:webUser.getBalance());
      }*/ else  if(webUserCachTypeEnum.getType() == WebUserCachTypeEnum.HefanTotal_type.getType()) { //累计盒饭
                return initUserCachSing(userId,webUserCachTypeEnum, webUser.getHefanTotal() == null ?0L:webUser.getHefanTotal());
            } /*else if (webUserCachTypeEnum.getType() == WebUserCachTypeEnum.PayCount_type.getType()) { //贡献值
                this.initUserCachSing(webUser.getUserId(),WebUserCachTypeEnum.PayCount_type, webUser.getPayCount() == null ?0L:webUser.getPayCount());
            }*/
    }
    return null;
  }

  /**
   * 主播排行榜
   * //TODO (这里用一句话描述这个方法的作用 - 必填)
   *
   * @param type 0:积分，1盒饭
   * @param page
   * @return
   * @throws
   * @description （用一句话描述该方法的适用条件、执行流程、适用方法、注意事项 - 可选）
   * @author wangchao
   * @create 2016/12/7 9:57
   */
  @Override
  public Page<Map<String, Object>> getAnchorRankingList(int type, Page<Map<String, Object>> page) throws Exception {
    String key = type == 0 ? RedisKeyConstant.ANCHOR__RANKING_LIST : RedisKeyConstant.ANCHOR__HF_RANKING_LIST;
    //新增获取月榜的redisKey
    if(type==2){
      key = RedisKeyConstant.ANCHOR__HF_RANKING_LIST_EVERYMONTH;
    }
    return jedisService.getObjectByPage(key, page);
  }

  @Override
  public void cacheAnchorRanking(int type, Map map) throws Exception {
    String key = type == 0 ? RedisKeyConstant.ANCHOR__RANKING_LIST : RedisKeyConstant.ANCHOR__HF_RANKING_LIST;
    //新增获取月榜的redisKey
    if(type==2){
      key = RedisKeyConstant.ANCHOR__HF_RANKING_LIST_EVERYMONTH;
    }
    Calendar ca = Calendar.getInstance();
    ca.add(Calendar.MONTH,1);
    ca.set(ca.get(Calendar.YEAR), ca.get(Calendar.MONTH), 1, 0, 0, 0);
    Calendar now = Calendar.getInstance();
    int expiredTime = (int) ((ca.getTimeInMillis() -now.getTimeInMillis())/ 1000);
    jedisService.cacheObjectWithSort(key, map.get("userId").toString(), map, Double.valueOf(map.get("ticketHistory").toString()), expiredTime);
  }

  /**
   * 扣费（（直播间/俱乐部）礼物，红包）成功后更新主播排行榜，总榜，月榜
   * 如果送礼人是内部用户或黑名单则不更新榜单
   *
   * @param fromId
   * @param userId   主播id
   * @return
   * @throws
   * @author wangchao
   * @create 2017/2/7 11:51
   */
  @Override
  @Deprecated
  public void updateRankByRebalance(String fromId, String authId, int heFanNum) throws Exception {
    Map<String, String> map = userConfigCenter.getPublicConfig();
    String blackList = StringUtils.isBlank(map.get("rankBlackList")) ? "" : map.get("rankBlackList");
    String[] lists = blackList.split(",");
    //0.黑名单用户不计算
    if (Arrays.asList(lists).contains(fromId)) {
      logger.error("更新主播排行榜错误：送礼人{}信息存在于黑名单中", fromId,blackList);
      return;
    }
    //1.查询送礼人是否内部用户
    WebUser webUser = webUserDao.getWebUserBaseInfo(fromId);
    if (webUser.getUserType() == UserTypeEnum.INTERNALLY_USER.getUserType()) {
      logger.error("更新主播排行榜错误：送礼人{}为内部用户", fromId);
      return;
    }
    long multiple = StringUtils.isBlank(map.get("multiple")) ? 10 : Long.parseLong(map.get("multiple"));
    //2.月榜
    try {
      String key = RedisKeyConstant.ANCHOR__HF_RANKING_LIST_EVERYMONTH + RedisKeyConstant.KEY_RECORD + authId;
      //2.1用户月榜不存在
      if (!jedisService.isExist(key)) {
        //重新计算主播本月实际收入扣除内部用户，黑名单，写入缓存
        logger.info("主播{}不在月榜中，月榜新增", authId);
        webUserService.getUserMonthRankingData(authId);
      } else {
        logger.info("主播{}存在月榜中，月榜更新{}积分", heFanNum * multiple);
        double total = jedisService.zincrby2(RedisKeyConstant.ANCHOR__HF_RANKING_LIST_EVERYMONTH + RedisKeyConstant.KEY_ACTIVE_LIST, heFanNum * multiple, authId);
        jedisService.hset(RedisKeyConstant.ANCHOR__HF_RANKING_LIST_EVERYMONTH + RedisKeyConstant.KEY_RECORD + authId, "ticketHistory", String.valueOf((long)total));
      }
    } catch (Exception e) {
      logger.error("更新主播月榜异常", e);
    }
    //3.总榜
    try {
      String key = RedisKeyConstant.ANCHOR__RANKING_LIST + RedisKeyConstant.KEY_RECORD + authId;
      //3.1用户月榜不存在
      if (jedisService.zrevrank2(RedisKeyConstant.ANCHOR__RANKING_LIST + RedisKeyConstant.KEY_ACTIVE_LIST, authId) == -1 || !jedisService.isExist(key)) {
        //重新计算主播本月实际收入扣除内部用户，黑名单，写入缓存
        logger.info("主播{}不在总榜中，总榜redis新增", authId);
        webUserService.getUserRankingData(authId, 0);
      } else {
        logger.info("主播{}存在总榜中，总榜redis更新{}积分", heFanNum * multiple);
        double total = jedisService.zincrby2(RedisKeyConstant.ANCHOR__RANKING_LIST + RedisKeyConstant.KEY_ACTIVE_LIST, heFanNum * multiple, authId);
        jedisService.hset(RedisKeyConstant.ANCHOR__RANKING_LIST + RedisKeyConstant.KEY_RECORD + authId, "ticketHistory", String.valueOf((long)total));
      }
      long position=jedisService.zrevrank(RedisKeyConstant.ANCHOR__RANKING_LIST + RedisKeyConstant.KEY_ACTIVE_LIST, authId);
      logger.info("主播{}总榜排名{}", authId, position);
      if (position < 5) {
        webUserService.syncOSS();
      }
    } catch (Exception e) {
      logger.error("更新主播总榜异常", e);
    }
  }

  @Override
  public Integer getToClubIndex(String userId) {
    String key = String.format(RedisKeyConstant.FIRST_TO_CLUB_ALERT,userId);
    Integer toClubIndex = 1;
    try {
        if(jedisService.isExist(key)){
          toClubIndex = 0;
        }
    } catch (Exception e) {
      logger.error("获取首次进入俱乐部状态失败 redis异常");
      e.printStackTrace();
    }
    return toClubIndex;
  }

  @Override
  public void setToClubIndex(String userId) {
    String key = String.format(RedisKeyConstant.FIRST_TO_CLUB_ALERT,userId);
    try {
      jedisService.set(key,"0");
    } catch (Exception e) {
      logger.error("设置首次进入俱乐部状态失败 redis异常");
      e.printStackTrace();
    }
  }


  /**
   * 在缓存中获取首次进入俱乐部推荐数据
   * @return
     */
  @Override
  public List recommendAnchorFirstCache(String userId){
    logger.info("删除用户首次进入俱乐部状态");
    delToClubIndex(userId);
    String listStr = null;
    try {
      listStr = jedisService.getStr(RedisKeyConstant.FIRST_TO_CLUB_ALERT_DATA);
    } catch (Exception e) {
      logger.error("获取首次进入俱乐部推荐缓存数据取出异常！！！"+e.getMessage());
      e.printStackTrace();
      return webUserService.recommendAnchorFirst(userId);
    }
    if(!StringUtils.isEmpty(listStr)){
      return JSONObject.parseObject(listStr,List.class);
    }else{
      List list = null;
      list=  webUserService.recommendAnchorFirst(userId);
      try {
        jedisService.setexStr(RedisKeyConstant.FIRST_TO_CLUB_ALERT_DATA,JSONObject.toJSONString(list),60*60*5);
      } catch (Exception e) {
        logger.error("设置首次进入俱乐部缓存设置失败！！redis异常"+e.getMessage());
        e.printStackTrace();
      }
      return list;
    }
  }


  private void delToClubIndex(String userId){
    String key = String.format(RedisKeyConstant.FIRST_TO_CLUB_ALERT,userId);
    try {
      jedisService.del(key);
    } catch (Exception e) {
      logger.error("删除用户首次进入俱乐部状态失败 redis异常");
      e.printStackTrace();
    }
  }



}
